//
//  AsyncSocket+RACSignal.m
//  高仿暴走斗图
//
//  Created by key on 16/4/1.
//  Copyright © 2016年 huangsongyao. All rights reserved.
//

#import "AsyncSocket+RACSignal.h"
#import "RACDelegateProxy.h"
#import "RACSignal+Operations.h"
#import "NSObject+RACDeallocating.h"
#import "NSObject+RACDescription.h"
#import <objc/runtime.h>

@implementation AsyncSocket (RACSignal)


static void RACUseDelegateProxy(AsyncSocket *self) {
    
    if (self.delegate == self.rac_delegateProxy) return;
    
    self.rac_delegateProxy.rac_proxiedDelegate = self.delegate;
    self.delegate = (id)self.rac_delegateProxy;
}

- (RACDelegateProxy *)rac_delegateProxy {
    
    RACDelegateProxy *proxy = objc_getAssociatedObject(self, _cmd);
    if (proxy == nil) {
        proxy = [[RACDelegateProxy alloc] initWithProtocol:@protocol(AsyncSocketDelegate)];
        objc_setAssociatedObject(self, _cmd, proxy, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }
    
    return proxy;
}

- (RACSignal *)rac_willDisconnect {
    
    RACSignal *signal = [[[[self.rac_delegateProxy
                            signalForSelector:@selector(onSocket:willDisconnectWithError:)]
                           reduceEach:^(AsyncSocket *socket, NSError *error) {
                               
                               NSDictionary *dic = @{
                                                     kSOCKET : socket,
                                                     kERROR  : error,
                                                     };
                               return dic;
                           }]
                          takeUntil:self.rac_willDeallocSignal]
                         setNameWithFormat:@"%@ -rac_rac_willDisconnect", self.rac_description];
    
    RACUseDelegateProxy(self);
    
    return signal;
}

- (RACSignal *)rac_didConnectToHost {
    
    RACSignal *signal = [[[[self.rac_delegateProxy
                            signalForSelector:@selector(onSocket:didConnectToHost:port:)]
                           reduceEach:^(AsyncSocket *socket, NSString *host) {
                               
                               NSDictionary *dic = @{
                                                     kSOCKET : socket,
                                                     kHSOT   : host,
                                                     };
                               return dic;
                           }]
                          takeUntil:self.rac_willDeallocSignal]
                         setNameWithFormat:@"%@ -rac_didConnectToHost", self.rac_description];
    
    RACUseDelegateProxy(self);
    
    return signal;

}


- (RACSignal *)rac_onSocketDidDisconnect {
    
    RACSignal *signal = [[[[self.rac_delegateProxy
                            signalForSelector:@selector(onSocketDidDisconnect:)]
                           reduceEach:^(AsyncSocket *socket) {
                               return socket;
                           }]
                          takeUntil:self.rac_willDeallocSignal]
                         setNameWithFormat:@"%@ -rac_onSocketDidDisconnect", self.rac_description];
    
    RACUseDelegateProxy(self);
    
    return signal;
}


- (RACSignal *)rac_didReadData {
    
    RACSignal *signal = [[[[self.rac_delegateProxy
                            signalForSelector:@selector(onSocket:didReadData:withTag:)]
                           reduceEach:^(AsyncSocket *socket, NSData *data, long tag) {
                               
                               NSDictionary *dic = @{
                                                     kSOCKET : socket,
                                                     kDATA   : data,
                                                     kTAG    : @(tag),
                                                     };
                               return dic;
                           }]
                          takeUntil:self.rac_willDeallocSignal]
                         setNameWithFormat:@"%@ -rac_didReadData", self.rac_description];
    
    RACUseDelegateProxy(self);
    
    return signal;
}


- (RACSignal *)rac_didWriteDataWithTag {
    
    RACSignal *signal = [[[[self.rac_delegateProxy
                            signalForSelector:@selector(onSocket:didWriteDataWithTag:)]
                           reduceEach:^(AsyncSocket *socket, long tag) {
                               
                               NSDictionary *dic = @{
                                                     kSOCKET : socket,
                                                     kTAG    : @(tag),
                                                     };
                               return dic;
                           }]
                          takeUntil:self.rac_willDeallocSignal]
                         setNameWithFormat:@"%@ -rac_didWriteDataWithTag", self.rac_description];
    
    RACUseDelegateProxy(self);
    
    return signal;
}


@end
